/*
 * @FileName: app_fsm.c
 * @Author: GreyQiu qiushaogui@aikosolar.com
 * @Date: 2023-07-17 15:53:58
 * @LastEditors: GreyQiu qiushaogui@aikosolar.com
 * @LastEditTime: 2023-09-25 10:40:46
 * @Description: 
 * 
 * Copyright (c) 2023, All Rights Reserved. 
 */

#include "app_fsm.h"
#include "app_fault.h"
#include "app_analog.h"
#include "app_mppt.h"
#include "fsm.h"
#include "bsp.h"
#include "dev_info.h"
#include "loop.h"

#define FSM_RUN_TS 1 // 状态机运行周期1ms

fsm_t fsm_buck;

static void act_ready_ramp(void);
static void act_ramp_normal(void);
static void act_ramp_run(void);
static void act_normal_run(void);
static void act_jump2shutdown(void);

static event_t chk_init(void);
static event_t chk_ready(void);
static event_t chk_ramp(void);
static event_t chk_normal(void);
static event_t chk_shutdown(void);
static event_t chk_hiccup(void);

/**
 * @description: 事件驱动状态跳转 状态跳转表
 */
static uint8_t sta_tbl[STATE_NUM][EVENT_NUM] =
{
    /*EVENT_NONE*/      /*EVENT_NORMAL*/    /*EVENT_ABNORMAL*/
    {STATE_INIT,        STATE_READY,        STATE_SHUTDOWN}, // STATE_INIT
    {STATE_READY,       STATE_RAMPUP,       STATE_SHUTDOWN}, // STATE_READY
    {STATE_RAMPUP,      STATE_NORMAL,       STATE_SHUTDOWN}, // STATE_RAMPUP
    {STATE_NORMAL,      STATE_NORMAL,       STATE_SHUTDOWN}, // STATE_NORMAL
    {STATE_SHUTDOWN,    STATE_READY,        STATE_SHUTDOWN},  // STATE_SHUTDOWN
    {STATE_HICCUP,      STATE_RAMPUP,       STATE_SHUTDOWN},  // STATE_HICCUP
};

/**
 * @description: 事件驱动执行动作 动作执行表
 */
static sta_action_t act_tbl[STATE_NUM][EVENT_NUM] =
{
    /*EVENT_NONE*/      /*EVENT_NORMAL*/    /*EVENT_ABNORMAL*/
    {NULL,              NULL,               NULL}, // STATE_INIT
    {NULL,              act_ready_ramp,     act_jump2shutdown}, // STATE_READY
    {act_ramp_run,      act_ramp_normal,    act_jump2shutdown}, // STATE_RAMPUP
    {act_normal_run,    act_jump2shutdown,  act_jump2shutdown}, // STATE_NORMAL
    {NULL,              NULL,               NULL},  // STATE_SHUTDOWN
    {NULL,              act_ready_ramp,     act_jump2shutdown},  // STATE_HICCUP
};

/**
 * @description: 每个状态对应的事件检查函数
 */
static sta_check_t check_tbl[STATE_NUM] =
{
    chk_init,       // STATE_INIT
    chk_ready,      // STATE_READY
    chk_ramp,       // STATE_RAMPUP
    chk_normal,     // STATE_NORMAL
    chk_shutdown,   // STATE_SHUTDOWN
    chk_hiccup,     // STATE_HICCUP
};

float Voc = 75.0f;

// ready跳转至ramp的执行动作
static void act_ready_ramp(void)
{
    Voc = asignal_get_real_flt(ANALOG_ID_VIN);

    // 环路清0
    loop_clear(&pid_pv1_vin);
    loop_clear(&pid_pv1_iin);
    loop_clear(&pid_pv1_vout);

    // 设定环路基准初始值
    loop_setRef(&pid_pv1_vout, asignal_get_real_flt(ANALOG_ID_VOUT));
    loop_setRef(&pid_pv1_iin, 0.0f);
    loop_setRef(&pid_pv1_vin, Voc * 0.95f);

    // 使能PWM输出
    bsp_pwm_duty_set(EPWM1_BASE, 0);
    bsp_pwm_duty_set(EPWM2_BASE, PWM_PERIOD_CNT);
    bsp_pwm_output_enable(EPWM1_BASE);
    bsp_pwm_output_enable(EPWM2_BASE);
    loop_enable(); // 环路使能
}

// ready跳转至ramp的执行动作
static void act_ramp_normal(void)
{
    app_mppt_init(MPPT_ID_FAST, Voc, Voc * 0.95f);
    app_mppt_enable(MPPT_ID_FAST);
}

// 逐步展开电压环基准
static void act_ramp_run(void)
{
    #define RAMP_TIME (5000) // 缓启时间5000ms
    float ramp_step1 =  (g_device_info.voutMax / RAMP_TIME * FSM_RUN_TS);
    float goal1 = pid_pv1_vout.ref;

    goal1 += ramp_step1;
    if (goal1 > g_device_info.voutMax)
    {
        goal1 = g_device_info.voutMax;
    }

    loop_setRef(&pid_pv1_vout, goal1);
}

static void act_normal_run(void)
{

}

static void act_jump2shutdown(void)
{
    // 禁止PWM输出
    bsp_pwm_output_disable(EPWM1_BASE);
    bsp_pwm_output_disable(EPWM2_BASE);
    loop_disable(); // 环路禁止
    bsp_pwm_duty_set(EPWM1_BASE, 0);
    bsp_pwm_duty_set(EPWM2_BASE, PWM_PERIOD_CNT);

    loop_disable(); // 环路禁止

    app_mppt_disable(MPPT_ID_FAST);
}


static event_t chk_init(void)
{
    // 首次开机等待3秒
    if (fsm_is_timeout(&fsm_buck, 3000)) { // 等待3000ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}


static event_t chk_ready(void)
{
    if (app_fault_get_bits() != 0) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    // 没有故障并且维持2秒，则可以返回正常事件
    if (fsm_is_timeout(&fsm_buck, 2000)) { // 等待2000ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}

static event_t chk_ramp(void)
{
    if (app_fault_get_bits() != 0) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    // 判断环路基准完全放开,跳转至下一状态
    if (pid_pv1_vout.ref == g_device_info.voutMax) {
        return EVENT_NORMAL;
    }
    return EVENT_NONE;
}

static event_t chk_normal(void)
{
    if (app_fault_get_bits() != 0) { // 检查是否有故障
        fsm_time_reset(&fsm_buck);
        return EVENT_ABNORMAL;
    }

    return EVENT_NONE;
}

static event_t chk_shutdown(void)
{
    if (app_fault_get_bits() != 0) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }
    fsm_time_reset(&fsm_buck);

    return EVENT_NORMAL;
}

static event_t chk_hiccup(void)
{
    if (app_fault_get_bits() != 0) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    if (fsm_is_timeout(&fsm_buck, 50)) { // 等待200ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}

void app_fsm_init(void)
{
    fsm_config(&fsm_buck, sta_tbl, act_tbl, check_tbl);
    fsm_buck.sta_cur = STATE_INIT;
    fsm_buck.time = 0;
}

void app_fsm_run(void)
{
    fsm_handler(&fsm_buck);
}

uint8_t fsm_get_status(void)
{
    return fsm_buck.sta_cur;
}
